package com.swak.frame.extension.adapter;

import java.util.Objects;
import java.util.Set;

import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.SmartInitializingSingleton;

import com.swak.frame.context.BoundContext;
import com.swak.frame.dto.base.BizScenario;
import com.swak.frame.extension.executor.ExtensionExecutor;
import com.swak.frame.extension.provider.WhiteListExtPtProvider;

public class WhiteListAdapter implements SmartInitializingSingleton {

	private Logger logger = LoggerFactory.getLogger(this.getClass());

	private ExtensionExecutor extensionExecutor;

	private WhiteListExtPtProvider whiteListExtPtProvider;

	public WhiteListAdapter(ExtensionExecutor extensionExecutor) {
		this.extensionExecutor = extensionExecutor;
	}

	public boolean isWhiteList(BoundContext resource) {
		boolean enabled = whiteListExtPtProvider.enable(resource);
		// 未开启直接过
		if (!enabled) {
			return true;
		}

		Set<String> whiteList = whiteListExtPtProvider.getConfig(resource);
		// 白名单属性是否配置,未配置放行
		if (CollectionUtils.isEmpty(whiteList)) {
			return true;
		}

		// 获取开启白名单的接口
		Set<String> authCode = whiteListExtPtProvider.getAuthCode(resource);

		String pin = resource.getRequest().getPin();

		// authCode未设置，全部接口校验
		if (CollectionUtils.isEmpty(authCode)) {
			return match(pin, whiteList);
		}

		// authCode设置，校验设置的接口
		if (authCode.contains(resource.getAuthCode())) {
			return match(pin, whiteList);
		}
		// 未设置的通过
		return true;
	}

	private boolean match(String pin, Set<String> whiteList) {
		boolean isMatch = whiteList.stream().anyMatch(wpin -> Objects.equals(wpin, pin));
		// 不匹配，说明该pin不在白名单中，不放行
		if (!isMatch) {
			logger.warn("白名单校验失败! PIN：{},whiteList:{} 请联系管理员确认白名单是否配置!", new Object[] { pin, whiteList });
		}
		return isMatch;
	}

	@Override
	public void afterSingletonsInstantiated() {
		if (whiteListExtPtProvider == null) {
			this.whiteListExtPtProvider = extensionExecutor.locateComponent(WhiteListExtPtProvider.class,
					BizScenario.valueOf(WhiteListExtPtProvider.WHITE_LIST_BIZ_ID));
		}
	}
}
